/**
 * @description InfiniteScroll 滚动加载
 * @author chenwenhao576
 * Example
 *
 * Html
 *   <seed-infinite-scroll
 *     (infiniteScroll)="onScroll($event)"
 *     [distance]='2 '
 *     [throttle]='300'
 *   >
 *      <seed-badges  [articles]="tools.setArray(articles | async)"></seed-badges>
 *      <seed-infinite-scroll-content
 *        [loadingText]='加载更多数据'
 *        [finishedText]='没有更多数据了'
 *      ></seed-infinite-scroll-content>
 *   </seed-infinite-scroll>
 *
 * TS
 *    @ViewChild(SeedInfiniteScroll) infiniteScroll;
 *
 *    onScroll(event){
 *      this.homeService.GetCateArticles(this.cateId,this.page)
 *         .debounceTime(800)
 *         .subscribe((res) => {
 *           this.infiniteScroll.complete();
 *           if (res && res.result == 0) {
 *             this.page++;
 *             if(res.data.hasNextPage == false){
 *               this.infiniteScroll.enable(false)
 *             }
 *             this.homeService.dataStore.articles = [...this.homeService.dataStore.articles,...res.data.list];
 *             this.homeService._articles.next(this.homeService.dataStore.articles);
 *           }
 *         });
 *     }
 *
 *  Intro
 *    (infiniteScroll) 此函数为滚动到底部加载触发函数,一般用来请求数据,为了更好的体验(显示出加载图标)建议在在函数subscribe时,
 *  加一个debounceTime(800),如line 21;
 *    complete() 此函数为请求到数据后如果返回数据完成调用此函数,避免重复请求,如line 26;
 *    enable() 完成请求数据用后如果没有下一页了,调用此函数传入'false',infinite scroll就解除监听滚动停止工作,
 *  传入'true',infinite scroll恢复监听,开始工作,如line 30;
 *    [distance] 设置滚动到底部距离出发加载更多函数默认为2,如无需改变可不需设置;
 *    [throttle] 节流器,默认为300,如无需改变可不需设置;
 *    [loadingText] 数据加载中显示的文字,默认为'加载更多数据',如无需改变可不需设置;
 *    [finishedText] 数据请求结束后,如没有更多数据了,显示的文字,默认为'加载更多数据',如无需改变可不需设置;
 *
 *  !Important
 *  <seed-infinite-scroll></seed-infinite-scroll>必须与<seed-infinite-scroll-content></seed-infinite-scroll-content>
 *  一起调用并且格式如下:
 *  Html:
 *   <seed-infinite-scroll
 *   >
 *    <div class='some-data>some data...</div>  //要滚动加载的内容;
 *     <seed-infinite-scroll-content
 *     ></seed-infinite-scroll-content>
 *   </seed-infinite-scroll>
 *
 * 为了避免不必要的麻烦,务必阅读此文档,并严格遵守相关格式;
 *
 * All by chenwenhao576
 */
import {
  Component, OnInit, Input, Output, EventEmitter, ElementRef, Inject, ViewEncapsulation
} from '@angular/core';
import {DOCUMENT} from "@angular/platform-browser";

@Component({
  selector: 'seed-infinite-scroll',
  templateUrl: './seed-infinite-scroll.component.html',
  styleUrls: ['./seed-infinite-scroll.component.scss'],
  host: {
    '[attr.state]': 'state'
  },
  encapsulation: ViewEncapsulation.None,
})
export class SeedInfiniteScroll implements OnInit {

  public STATE_ENABLED = 'enabled';
  public STATE_DISABLED = 'disabled';
  public STATE_LOADING = 'loading';
  public _distance: number;
  public _throttle: number;
  public _container: any;

  public state = this.STATE_ENABLED;

  /**
   * @description 设置滚动到底部距离出发加载更多函数默认为2
   * @returns {number}
   */
  @Input()
  get distance(): number {
    return this._distance;
  }

  set distance(val: number) {
    this._distance = val;
  }

  @Input()
  get throttle(): number {
    return this._throttle;
  }

  set throttle(val: number) {
    this._throttle = val;
  }

  /**
   * @description 设置滚动触发的容器，本程序默认容器为seed-content组件里的滚动
   * @returns {any}
   */
  @Input()
  get container(): ElementRef {
    return this._container;
  }

  set container(val: ElementRef) {
    this._container = val;
  }

  /**
   * @description 滚动到底触发的函数
   * @type {EventEmitter<any>}
   */
  @Output()
  infiniteScroll: EventEmitter<any> = new EventEmitter<any>();

  constructor(@Inject(DOCUMENT) private document) {
    this._distance = 2;
    this._throttle = 300;
  }

  onScroll() {
    if (this.state !== this.STATE_ENABLED) {
      return;
    }
    this.infiniteScroll.emit();
    this.state = this.STATE_LOADING;
  }

  /**
   * @description infinite scroll后（infiniteScroll）= someFuncion里面的函数请求
   * 数据后如果返回数据完成后调用此函数,避免重复请求
   */
  complete() {
    if (this.state !== this.STATE_LOADING) {
      return;
    }
    this.state = this.STATE_ENABLED;
  }

  /**
   * @description infinite scroll完成调用后如果没有下一页了
   * 调用此函数传入'false',infinite scroll就不会工作,
   * 传入true,infinite scroll开始工作
   * @param shouldEnable boolean
   */
  enable(shouldEnable: boolean) {
    this.state = (shouldEnable ? this.STATE_ENABLED : this.STATE_DISABLED);
  }


  /**
   * 如不理解,请查看顶部相关提示文档.
   */
  ngOnInit() {
    this.container = this.document.querySelector('#seed-scroll-content') || this.document.body;
  }

}
